package com.park.utils.wx;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.park.comm.WxComm;
import com.park.entity.wx.*;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * @title: WxUtils
 * @projectName park
 * @description: 微信工具类
 * @date 2020/5/122:34
 */
@Slf4j
public class WxUtils {

    /**
     　　* @description: 微信获取凭证
     　　* @param [appid 小程序唯一凭证，即 AppID，可在「微信公众平台 - 设置 - 开发设置」页中获得。（需要已经成为开发者，且帐号没有异常状态）
                , secret 小程序唯一凭证密钥，即 AppSecret，获取方式同 appid]
     　　* @return {@link WxAccessTokenReturnData} 凭证 有效期
     　　* @throws
     　　* @author ZhangHaiWen
     　　* @version 2.0
     　　* @date 2020/5/1 22:48
     　　*/
    public static  WxAccessTokenReturnData getAccessToken(String appid,String secret){
        String url = String.format(WxComm.WX_GETTOKEN_URL,appid,secret);
        String accessTokenJson= HttpUtil.get(url);
        WxAccessTokenReturnData wxAccessTokenReturnData = JSONUtil.toBean(accessTokenJson, WxAccessTokenReturnData.class);
        return wxAccessTokenReturnData;
    }

    /**
     　　* @description: 微信 获取session接口
     　　* @param [appid :小程序唯一凭证，即 AppID，可在「微信公众平台 - 设置 - 开发设置」页中获得。（需要已经成为开发者，且帐号没有异常状态）,
                  secret : 小程序唯一凭证密钥，即 AppSecret，获取方式同 appid
                  jsCode : 登录时获取的 code 小程序调用 wx.login() 获得]
     　　* @return {@link String}
     　　* @throws
     　　* @author ZhangHaiWen
     　　* @version 2.0
     　　* @date 2020/5/1 22:54
     　　*/
    public static Code2SessionReturnData code2Session(String appid, String secret, String jsCode){
        String url = String.format(WxComm.WX_CODE2SESSION_URL,appid,secret,jsCode);
        String accessTokenJson= HttpUtil.get(url);
        Code2SessionReturnData code2SessionReturnData = JSONUtil.toBean(accessTokenJson, Code2SessionReturnData.class);
        return code2SessionReturnData;
    }

    /**
     　　* @description: wx调用getUserInfo 获取用户数据
     　　* @param [encryptedData 加密数据串, sessionKey 会话秘钥[Code2SessionReturnData 获取的数据], iv 偏移量]
     　　* @return {@link UserInfoReturnData}
     　　* @throws
     　　* @author ZhangHaiWen
     　　* @version 2.0
     　　* @date 2020/5/2 7:09
     　　*/
    public static UserInfoReturnData getUserInfo(String encryptedData,String sessionKey,String iv){
        String userInfoJson = AesCbcUtil.decrypt(encryptedData, sessionKey, iv);
        UserInfoReturnData userInfoReturnData = JSONUtil.toBean(userInfoJson, UserInfoReturnData.class);
        return userInfoReturnData;
    }

    /**
     　　* @description: wx调用 getPhoneNumber  获取用户数据
     　　* @param [encryptedData 加密数据串, sessionKey 会话秘钥, iv 偏移量]
     　　* @return {@link UserInfoReturnData}
     　　* @throws
     　　* @author ZhangHaiWen
     　　* @version 2.0
     　　* @date 2020/5/2 7:09
     　　*/
    public static PhoneNumberReturnData getPhoneNumber(String encryptedData, String sessionKey, String iv){
        String phoneNumberJson = AesCbcUtil.decrypt(encryptedData, sessionKey, iv);
        PhoneNumberReturnData phoneNumberReturnData = JSONUtil.toBean(phoneNumberJson, PhoneNumberReturnData.class);
        return phoneNumberReturnData;
    }

    /**
     　　* @description: wx调用 校验 signature
     　　* @param [rawData 不包括敏感信息的原始数据字符串，用于计算签名,sessionKey 绘画密钥]
     　　* @return {@link UserInfoReturnData}
     　　* @throws
     　　* @author ZhangHaiWen
     　　* @version 2.0
     　　* @date 2020/5/2 7:09
     　　*/
    public static String getSignature(String rawData,String sessionKey){
        String signature = AesCbcUtil.encodeSha1(rawData + sessionKey);
        return signature;
    }


    /**
     * 微信统一下单
     * @return
     */
    public static Map<String, String> unifiedorder(String body, String orderNo, BigDecimal totalFee, String ip,String openid){
        try {
            //统一下单
            BigDecimal multiply = totalFee.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_EVEN);
            Map<String, String> requestData = fillRequestData();
            requestData.put("body", body);                          //商品描述
            requestData.put("out_trade_no", orderNo);               //商品订单号
            requestData.put("total_fee", multiply.toString());      //真实金额 订单总金额，单位为分
            requestData.put("spbill_create_ip", ip);                //支付ip
            requestData.put("notify_url", WxComm.WX_PAY_CALLBACK);  //异步回调api
            requestData.put("trade_type", "JSAPI");                 //APP调用
            requestData.put("openid",openid);
            //统一下单
            MiniWXPayConfig miniWXPayConfig = MiniWXPayConfig.SingleWXPayConfig.INSTENCE.getInstence();
            WXPay wxPay = new WXPay(miniWXPayConfig);
            Map<String, String> resultMap = wxPay.unifiedOrder(requestData);
            log.info("统一下单:{}",resultMap);
            //获取返回参数
            String return_code = resultMap.get("return_code");
            if(return_code.equals("SUCCESS")){
                //再次签名
                Map<String, String> signAgainMap = new HashMap<String, String>();
                signAgainMap.put("appId", WxComm.USER_APPID);
                signAgainMap.put("timeStamp",String.valueOf(Instant.now().getEpochSecond()));
                signAgainMap.put("nonceStr",WXPayUtil.generateNonceStr());
                signAgainMap.put("package","prepay_id="+resultMap.get("prepay_id"));
                signAgainMap.put("signType", WXPayConstants.MD5);
                signAgainMap.put("paySign",WXPayUtil.generateSignature(signAgainMap, WxComm.WX_APP_PAY_KEY, WXPayConstants.SignType.MD5));
                log.info("再次验签:{}",signAgainMap);
                return signAgainMap;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 生成包含签名的Map数据
     * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
     * 该函数适用于商户适用于统一下单等接口，不适用于红包、代金券接口
     * @param
     * @return
     * @throws Exception
     */
    public static Map<String, String> fillRequestData(){
        try {
            Map<String, String> reqData = new HashMap<String, String>();
            reqData.put("appid", WxComm.USER_APPID);
            reqData.put("mch_id", WxComm.WX_PAY_MCH_ID);
            reqData.put("nonce_str", WXPayUtil.generateNonceStr());
            reqData.put("sign_type", WXPayConstants.MD5);
            reqData.put("sign", WXPayUtil.generateSignature(reqData, WxComm.WX_APP_PAY_KEY, WXPayConstants.SignType.MD5));
            return reqData;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String body = "微信支付";
        String s = WXPayUtil.generateNonceStr();
        String orderNo = s;
        BigDecimal bigDecimal = new BigDecimal(1);
        String ip = "127.0.0.1";
        unifiedorder(body,orderNo,bigDecimal,ip,"oygRA5QeyjPfWCsUIKCdGaBhwQkI");
    }

}
